<template>
  <div class="camera-capture">
    <div v-if="!captured" class="camera-section">
      <video
        ref="videoRef"
        :width="width"
        :height="height"
        autoplay
        playsinline
        class="camera-video"
      ></video>
      <div class="capture-controls">
        <el-button type="primary" size="large" @click="capturePhoto" :loading="capturing">
          <el-icon><Camera /></el-icon>
          拍摄照片
        </el-button>
        <el-button @click="stopCamera" size="large">
          <el-icon><Close /></el-icon>
          停止摄像头
        </el-button>
      </div>
    </div>

    <div v-else class="preview-section">
      <canvas
        ref="canvasRef"
        :width="width"
        :height="height"
        class="preview-canvas"
      ></canvas>
      <div class="preview-controls" v-if="!showExternalButtons">
        <el-button @click="retakePhoto" size="large">
          <el-icon><RefreshRight /></el-icon>
          重新拍摄
        </el-button>
      </div>
    </div>

  </div>
</template>

<script setup>
import { ref, onMounted, onBeforeUnmount, nextTick, watch } from 'vue'

import { Camera, Close, RefreshRight } from '@element-plus/icons-vue'

const props = defineProps({
  width: {
    type: Number,
    default: 640
  },
  height: {
    type: Number,
    default: 480
  },
  showExternalButtons: {
    type: Boolean,
    default: false
  },
  reset: {
    type: Boolean,
    default: false
  }
})

const emit = defineEmits(['photo-captured', 'photo-confirmed', 'retake-photo'])

const videoRef = ref(null)
const canvasRef = ref(null)
const stream = ref(null)
const captured = ref(false)
const capturing = ref(false)
const photoBlob = ref(null)

onMounted(async () => {
  try {
    await startCamera()
  } catch (error) {
    console.error('Failed to start camera on mount:', error)
  }
})

onBeforeUnmount(() => {
  stopCamera()
})

// 监听reset属性，当为true时重置摄像头状态
watch(() => props.reset, (newVal) => {
  if (newVal) {
    resetCamera()
  }
})

const startCamera = async () => {
  try {
    // 如果已有流，先停止
    if (stream.value) {
      stopCamera()
    }
    
    stream.value = await navigator.mediaDevices.getUserMedia({ 
      video: { 
        width: props.width, 
        height: props.height,
        facingMode: 'user'
      } 
    })
    
    if (videoRef.value) {
      videoRef.value.srcObject = stream.value
      
      // 等待视频加载完成
      return new Promise((resolve, reject) => {
        const video = videoRef.value
        
        const onLoadedMetadata = () => {
          video.removeEventListener('loadedmetadata', onLoadedMetadata)
          video.removeEventListener('error', onError)
          
          // 确保视频开始播放
          video.play().then(() => {

            resolve()
          }).catch((playError) => {
            console.error('Error playing video:', playError)

            reject(playError)
          })
        }
        
        const onError = (error) => {
          video.removeEventListener('loadedmetadata', onLoadedMetadata)
          video.removeEventListener('error', onError)
          console.error('Video error:', error)

          reject(error)
        }
        
        video.addEventListener('loadedmetadata', onLoadedMetadata)
        video.addEventListener('error', onError)
        
        // 设置超时
        setTimeout(() => {
          video.removeEventListener('loadedmetadata', onLoadedMetadata)
          video.removeEventListener('error', onError)
          reject(new Error('视频加载超时'))
        }, 10000)
      })
    }
  } catch (error) {
    console.error('Error accessing camera:', error)
    if (error.name === 'NotAllowedError') {

    } else if (error.name === 'NotFoundError') {

    } else if (error.name === 'NotReadableError') {

    } else {

    }
    throw error
  }
}

const stopCamera = () => {
  if (stream.value) {
    stream.value.getTracks().forEach(track => track.stop())
    stream.value = null
  }
}

const capturePhoto = async () => {
  if (!videoRef.value || capturing.value) return
  
  const video = videoRef.value
  
  // 检查视频状态
  if (!video.srcObject) {

    return
  }
  
  if (video.readyState < 2) {

    return
  }
  
  if (video.paused || video.ended) {

    return
  }
  
  if (video.videoWidth === 0 || video.videoHeight === 0) {

    return
  }
  
  capturing.value = true
  
  try {
    // 先设置captured为true，让canvas渲染
    captured.value = true
    
    // 等待DOM更新，确保canvas已经渲染
    await nextTick()
    
    const canvas = canvasRef.value
    
    if (!canvas) {
      throw new Error('Canvas element not found')
    }
    
    const ctx = canvas.getContext('2d')
    
    // 清空canvas
    ctx.clearRect(0, 0, props.width, props.height)
    
    // 绘制当前视频帧到canvas
    ctx.drawImage(video, 0, 0, props.width, props.height)
    
    // 转换为Blob
    canvas.toBlob((blob) => {
      if (blob) {
        photoBlob.value = blob
        emit('photo-captured', blob)
        // 拍照完成后直接触发确认事件
        emit('photo-confirmed', blob)
      } else {
        // 如果转换失败，重置状态
        captured.value = false
      }
      capturing.value = false
    }, 'image/jpeg', 0.8)
    
  } catch (error) {
    console.error('Error capturing photo:', error)

    capturing.value = false
    captured.value = false // 重置状态
  }
}

const retakePhoto = async () => {
  emit('retake-photo')
  await resetCamera()
}

const resetCamera = async () => {
  captured.value = false
  photoBlob.value = null
  try {
    await startCamera()
  } catch (error) {
    console.error('Failed to restart camera:', error)
  }
}


</script>

<style scoped>
.camera-capture {
  text-align: center;
}

.camera-section, .preview-section {
  margin-bottom: 20px;
}

.camera-video, .preview-canvas {
  border: 2px solid #dcdfe6;
  border-radius: 10px;
  background-color: #f5f7fa;
}

.capture-controls, .preview-controls {
  margin-top: 15px;
}

.capture-controls .el-button,
.preview-controls .el-button {
  margin: 0 10px;
  border-radius: 20px;
}

</style>
